Technical Q&A QA1134
Programmatically causing restart, shutdown and/or logout


Q: How do I programmatically shutdown, restart, sleep or logout a machine running Mac OS 9 or Mac OS X?

A: You can do all of the above by sending specific Apple events to the Macintosh system process. The system process will interpret the Apple events and cause the requested event. On Mac OS 9 the system process was the Finder. On Mac OS X the system process is loginwindow. You can target the system process for Apple events using the constant {0,kSystemProcess} as the ProcessSerialNumber of the target application. Note that the restart, shutdown or logout sequence initiated using this method can be cancelled by running applications. For details on applications canceling the restart/shutdown/logout sequence see "Terminating Processes" in System Overview.

IMPORTANT:
Developers should only initiate a restart, shutdown, sleep or logout event when absolutely necessary. Also, these actions should only be undertaken after getting user consent.

In Mac OS 9 and Mac OS X a system restart or shutdown can be initiated by sending a kAERestart or kAEShutDown Apple event respectively to the system process. Sending the Apple Event will begin the restart or shutdown sequence.

Additionally, on Mac OS X logout and sleep events are available. A logout or sleep can be initiated by sending a kAEReallyLogOut or kAESleep event to the system process. Note previous to Mac OS X 10.2 kAEReallyLogOut was not defined in the Apple Event headers but was still supported. On previous Mac OS X versions developers can substitute the equivalent character code 'rlgo' for kAEReallyLogOut in their code.

The code below demonstrates how to programmatically cause restart, shutdown, sleep and logout by sending AppleEvents to the system process. The function SendAppleEventToSystemProcess does the work of sending the Apple Event to the system process. A full project with the below source code can be found in the qa1134.sit downloadable.


int main(void)
{
    const int bufferSize = 256;
    OSStatus error = noErr;
    char select [bufferSize];

    printf("1: Restart computer\n");
    printf("2: Shutdown computer\n");
    printf("3: Logout computer\n");
    printf("4: Sleep computer\n");
    printf("q: quit program\n");

    printf("please enter choice:\n");fflush(stdout);
    fgets(select, bufferSize, stdin);

    switch (select[0])
    {
         case '1':
            //sending restart event to system
            error = SendAppleEventToSystemProcess(kAERestart);
            if (error == noErr)
                {printf("Computer is going to restart!\n");}
            else
                {printf("Computer wouldn't restart\n");}
         break;
         case '2':
            //sending shutdown event to system
            error = SendAppleEventToSystemProcess(kAEShutDown);
            if (error == noErr)
                {printf("Computer is going to shutdown!\n");}
            else
                {printf("Computer wouldn't shutdown\n");}
         break;
         case '3':
            //sending logout event to system
            error = SendAppleEventToSystemProcess(kAEReallyLogOut);
            if (error == noErr)
                {printf("Computer is going to logout!\n");}
            else
                {printf("Computer wouldn't logout");}
         break;
         case '4':
            //sending sleep event to system
            error = SendAppleEventToSystemProcess(kAESleep);
            if (error == noErr)
                {printf("Computer is going to sleep!\n");}
            else
                {printf("Computer wouldn't sleep");}
    };

    return(0);
}

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
{
    AEAddressDesc targetDesc;
    static const ProcessSerialNumber
         kPSNOfSystemProcess = { 0, kSystemProcess };
    AppleEvent eventReply = {typeNull, NULL};
    AppleEvent appleEventToSend = {typeNull, NULL};

    OSStatus error = noErr;

    error = AECreateDesc(typeProcessSerialNumber,
        &kPSNOfSystemProcess, sizeof(kPSNOfSystemProcess),
        &targetDesc);

    if (error != noErr)
    {
        return(error);
    }

    error = AECreateAppleEvent(kCoreEventClass, EventToSend,
                     &targetDesc, kAutoGenerateReturnID,
                     kAnyTransactionID, &appleEventToSend);

    AEDisposeDesc(&targetDesc);

    if (error != noErr)
    {
        return(error);
    }

    error = AESend(&appleEventToSend, &eventReply, kAENoReply,
             kAENormalPriority, kAEDefaultTimeout,
             NULL, NULL);

    AEDisposeDesc(&appleEventToSend);

    if (error != noErr)
    {
        return(error);
    }

    AEDisposeDesc(&eventReply);

    return(error); //if this is noErr then we are successful
}

Listing 1. Demonstration of how to programatically restart, shutdown, sleep and logout the system


Downloadables

qa1134.sit

Source project for code listing one (8K)

Download



[Feb 10 2003]


Developer Documentation | Technical Notes | Development Kits | Sample Code